home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / overview / dave falkenburg's sprocket / lib / sprocketmain.cp < prev    next >
Encoding:
Text File  |  2000-09-28  |  17.0 KB  |  653 lines

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by:  Dave Falkenburg and many other SmartFriends™    
  7.  
  8.     Copyright:    Copyright © 1993-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 8/19/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 12/6/94        DRF                kUnresolvedSymbolAddress isn’t a Ptr in the latest universal
  21.                                             interfaces.
  22.                 11/23/94    DRF                InstallAppleEventHandlers is now called InitAppleEventRoutines.
  23.                 11/16/94    DRF                Added an explicit #include <Traps.h> for latest universal
  24.                                             headers. Also killed off a CFront warning.
  25.                 11/12/94    DRF                Revised QuickDrawGX initialization based on changes made by Jon
  26.                                             Summer. We now use a 'gasz' resource to setup the size of the
  27.                                             graphics heap. Also we are now always TSM aware, not just when
  28.                                             TSMTE is around.
  29.                 11/8/94        DRF                Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  30.                                             exists. Also, stop openning up the preferences file here.
  31.                  9/27/94        DRF                 AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  32.                                              and eliminated HandleUpdate.
  33.                  9/9/94        DRF                Reordered headers and removed redundant #includes.
  34.                                             Conditionalized AOCE support. Also made changes to
  35.                                             TSMEventWrapper to be more like the code in InlineInputSample.
  36.                  9/8/94        DRF                Add HiliteMenu(0) calls after calls to menu handling code
  37.                                             because TSMMenuSelect doesn’t do it. Also reorganized some GX
  38.                                             stuff: allocate and release a graphicsclient (Cam claims this
  39.                                             works on his machine), and turn on all the graphics errors and
  40.                                             notices if qDebug is set.
  41.                 9/7/94        DRF                Rearrange YieldToAnyThread calls to make quitting faster.
  42.                 9/4/94        DRF                Rearrange local variables in HandleMouseDown.
  43.                  9/1/94        DRF                Stop including "MailableWindow.h" here.
  44.                  9/1/94        DRF                More fixes for inline input, but we’re not really done yet.
  45.  
  46.  
  47. */
  48.  
  49. #include "Sprocket.h"
  50.  
  51. #include <limits.h>        //    For LONG_MAX
  52.  
  53. #include <Fonts.h>
  54. #include <Desk.h>
  55. #include <GestaltEqu.h>
  56. #include <DiskInit.h>
  57. #include <Threads.h>
  58. #include <CodeFragments.h>    //    for kUnresolvedSymbolAddress
  59. #include <Traps.h>
  60.  
  61. #if    qInlineInputAware
  62. #include <TextServices.h>
  63. #include <TSMTE.h>
  64. #endif
  65.  
  66. #if    qUseQuickDrawGX
  67. #include <graphics macintosh.h>
  68. #include <graphics routines.h>
  69. #include <graphics libraries.h>
  70. #include <PrintingManager.h>
  71. #endif
  72.  
  73. #include "StandardMenus.h"
  74. #include "Window.h"
  75. #include "SplashWindow.h"
  76. #include "AppleEventHandling.h"
  77.  
  78.  
  79. //    Function Prototypes
  80.  
  81. void    main(void);
  82. void    MainEventLoop(void);
  83.  
  84. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  85. void    HandleClose(WindowPtr aWindow);
  86.  
  87.  
  88. //    Globals
  89.  
  90. Boolean                gDone = false;
  91. Boolean                gMenuBarNeedsUpdate = true;
  92.  
  93. Boolean                gHasColorQuickdraw = false;
  94. Boolean                gHasThreadManager = false;
  95. Boolean                gHasDragManager = false;
  96. Boolean                gHasAppleScript = false;
  97. Boolean                gHasDisplayManager = false;
  98.  
  99. GrafPtr                gWindowManagerPort;
  100. Rect                gDeskRectangle;
  101. RgnHandle            gMouseRegion = nil;
  102.  
  103. short                gPreferencesRsrcRefNum;
  104.  
  105. #if    qAOCEAware
  106. Boolean                gHasAOCE = false;
  107. #endif
  108.  
  109. #if    qInlineInputAware
  110. Boolean                gHasTextServices = false;
  111. Boolean                gHasTSMTE = false;
  112.  
  113. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  114.  
  115. #endif
  116.  
  117. #if    qUseQuickDrawGX
  118. Boolean                gHasQuickDrawGX = false;
  119. long                gQuickDrawGXVersion = 0;
  120. long                gQuickDrawGXPrintingVersion = 0;
  121. gxGraphicsClient    gQuickDrawGXClient;
  122. #endif
  123.  
  124.  
  125. //    Values that can be adjusted by other application code to change
  126. //    the behavior of the MainEventLoop.
  127. //
  128. //    Rules of thumb:
  129. //
  130. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  131. //            The application has many threads running that need time
  132. //
  133. //        Decrease gXXXRunQuantum when:
  134. //            Sending AppleEvents to other applications
  135. //            Launching other applications
  136. //            Running in the background
  137.  
  138. unsigned long    gForegroundRunQuantum = 0;
  139. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  140. unsigned long    gBackgroundRunQuantum = 0;
  141. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  142.  
  143.  
  144. //    Globals used to “tune” the performance of MainEventLoop
  145. //    (assume we’ll be starting in the foreground)
  146.  
  147. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  148. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  149.  
  150. #ifdef    powerc
  151. #ifndef    __MWERKS__
  152. QDGlobals    qd;
  153. #endif
  154. #endif
  155.  
  156. void
  157. main(void)
  158.     {
  159.     long        feature;
  160.  
  161.     MaxApplZone();
  162.     MoreMasters();
  163.     MoreMasters();
  164.     MoreMasters();
  165.     MoreMasters();
  166.  
  167.     InitGraf(&qd.thePort);    
  168.     InitFonts();
  169.     InitWindows();
  170.     InitMenus();
  171.     TEInit();
  172.     InitDialogs(nil);
  173.  
  174.  
  175.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  176.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  177.  
  178.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  179.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  180.  
  181.     
  182.     TSplashWindow * splashWindow = new TSplashWindow;
  183.  
  184.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  185.     
  186. #if    qUseQuickDrawGX
  187.     //    Check for and initialize QuickDrawGX
  188.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  189.         {
  190.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  191.             {
  192. #ifdef    powerc
  193.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  194. #endif
  195.             gHasQuickDrawGX = true;
  196.             }
  197.         }
  198.  
  199.     if (gHasQuickDrawGX)
  200.         {
  201.         // Initialize the graphics and printing environments.
  202.         //    For additional details see "IM: QD GX Environment & Utilities."
  203.         
  204.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  205.         //    GX uses the first long word of that resource as the graphics heap size.
  206.         //    To determine the memory requirements of your graphics client heap see:
  207.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  208.         
  209.         //    NOTE:    If your application does not provide this resource,
  210.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  211.  
  212.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  213.         if (gQuickDrawGXClient)
  214.             {
  215.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  216.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  217.             //            while we have a chance to deal with things nicely.
  218.             //
  219.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  220.             
  221.             GXEnterGraphics();
  222.  
  223.             if (GXGetGraphicsError(nil) == noErr)
  224.                 {
  225. #if    qUseQuickDrawGXDebugging
  226.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  227.  
  228.                 //    NOTES from Jon Summers:
  229.                 //    As you increase the amount of validation, drawing speed will SLOW
  230.                 //    down due to all of the internal checking. Also, if you play with
  231.                 //    settings enough validation seems to become inconsistent
  232.  
  233.                 GXSetValidation(    //    gxInternalValidation    |
  234.                                     //    gxAllObjectValidation    |
  235.                                     //    gxApHeapValidation        |
  236.                                         gxPublicValidation);        // check parameters to public routines
  237.  
  238.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  239.                 //    If you don't have the debugging version installed, these functions will not work. 
  240.  
  241.                 SetGraphicsLibraryErrors();
  242.                 SetGraphicsLibraryNotices();    
  243. #endif
  244.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  245.                     {
  246.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  247.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  248.                     
  249.                     if (gQuickDrawGXClient)
  250.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  251.                     gHasQuickDrawGX = false;
  252.                     }
  253.                 }
  254.             }
  255.         }
  256.  
  257.     if (gQuickDrawGXClient)
  258.         InitCommonColors();        // Initialize the CommonColors Library.
  259. #if    qRequireQuickDrawGX
  260.     else
  261.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  262. #endif    //    qRequireQuickDrawGX
  263. #endif    //    qUseQuickDrawGX
  264.  
  265.  
  266.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  267.         (feature & (1 << gestaltAppleEventsPresent)))
  268.         {
  269.         //    Figure out if we need to do AppleEvent recording
  270.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  271.         }
  272.     else
  273.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  274.  
  275. #if    qInlineInputAware
  276.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  277.         {
  278.         gHasTextServices = true;
  279.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  280.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  281.  
  282.         if (InitTSMAwareApplication() != noErr)
  283.             {
  284.             gHasTextServices = false;
  285.             gHasTSMTE = false;
  286.             }
  287.         }
  288.  
  289. #endif
  290.  
  291.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  292.         {
  293. #ifdef    powerc
  294.         //    If running on a PowerPC, make sure that we not only have the
  295.         //    68K Thread Manager, but also the PowerPC shared library, too.
  296.         //    Because of the wonders of weak linking and out of memory errors
  297.         //    we need to also check to make sure that an entrypoint in the library
  298.         //    is there, too. 
  299.         if ((Ptr) NewThread != (Ptr) kUnresolvedCFragSymbolAddress)
  300.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  301. #else
  302.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  303. #endif
  304.         }
  305.  
  306. #if    qRequireThreadManager
  307.     if (gHasThreadManager == false)
  308.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  309. #endif
  310.  
  311.     //    Check for and install Drag Manager callbacks
  312.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  313.         {
  314. #ifdef    powerc
  315.         //    If running on a PowerPC, make sure that we not only have the
  316.         //    68K Drag Manager, but also the PowerPC shared library, too.
  317.         if ((Ptr) NewDrag != (Ptr) kUnresolvedCFragSymbolAddress)
  318.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  319. #else
  320.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  321. #endif
  322.  
  323.         if (gHasDragManager)
  324.             {
  325.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  326.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  327.             }
  328.         }
  329.  
  330.     //    Check for Display Manager
  331.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  332.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  333.  
  334. #if    qAOCEAware    
  335.     //    Check for and initialize AOCE Standard Mail package if it exists
  336.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  337.         {
  338. #ifdef    powerc
  339.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  340.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  341. #else
  342.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  343. #endif
  344.         }
  345. #endif
  346.  
  347.     //    Initialize our AppleEvent Handling Routines
  348.     InitAppleEventRoutines();
  349.  
  350.     //    Setup desktop rectangle for dragging windows around            
  351.     GetWMgrPort(&gWindowManagerPort);
  352.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  353.  
  354.     //    Get the default menubar
  355.     SetMenuBar(GetNewMBar(rMenuBar));
  356.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  357.  
  358.     // Add fonts to the font menu if it installed
  359.     if (GetMenuHandle(mFont))
  360.         AppendResMenu(GetMenuHandle(mFont),'FONT');
  361.     
  362.     if (SetupApplication() == noErr)
  363.         {
  364.         delete    splashWindow;    //    get rid of the splash screen
  365.         MainEventLoop();
  366.         TearDownApplication();
  367.         }
  368.  
  369. #if    qInlineInputAware
  370.     if (gHasTextServices)
  371.         (void) CloseTSMAwareApplication();
  372. #endif
  373.         
  374. #if    qUseQuickDrawGX
  375.     //    Tear down QuickDrawGX
  376.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  377.         {
  378.         DisposeCommonColors();
  379.         GXExitPrinting();        // Close the new printing mgr. 
  380.         GXExitGraphics();        // Deallocate all of the default structures
  381.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  382.         }
  383. #endif
  384.     }
  385.  
  386.  
  387. void
  388. MainEventLoop(void)
  389.     {
  390.     EventRecord        anEvent;
  391.     unsigned long    nextTimeToCheckForEvents = 0;
  392.     
  393.     while (!gDone)
  394.         {
  395.         if (gMenuBarNeedsUpdate)
  396.             {
  397.             gMenuBarNeedsUpdate = false;
  398.             DrawMenuBar();
  399.             }
  400.  
  401.         if (gHasThreadManager)
  402.             YieldToAnyThread();
  403.  
  404.         if ((gRunQuantum == 0) ||
  405.             (TickCount() > nextTimeToCheckForEvents))
  406.             {
  407.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  408.             
  409.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  410.                         
  411. #if    qInlineInputAware
  412.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  413.                 {
  414.                 }
  415.             else
  416. #endif
  417.                 HandleEvent(&anEvent);
  418.             }
  419.         }
  420.     }
  421.  
  422. #if    qInlineInputAware
  423.  
  424. Boolean
  425. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  426.     {
  427.     short        oldFont;
  428.     ScriptCode    keyboardScript;
  429.     Boolean        didTSMHandleTheEvent = false;
  430.  
  431.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  432.     //    and is related to working around a bug in Kotoeri, one of the
  433.     //    Japanese Input methods when operating in a mixed script
  434.     //    environment (e.g., Japanese Language Kit)
  435.     
  436.     // make sure we have a port and it's not the Window Manager port
  437.     if (qd.thePort != nil)
  438.         {
  439.         oldFont            = qd.thePort->txFont;
  440.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  441.  
  442.         if (FontToScript(oldFont) != keyboardScript)
  443.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  444.         }
  445.  
  446.     didTSMHandleTheEvent = TSMEvent(anEvent);
  447.     
  448.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  449.  
  450.     return didTSMHandleTheEvent;
  451.     }
  452.  
  453. #endif    
  454.  
  455.  
  456.  
  457. void
  458. HandleEvent(EventRecord *anEvent)
  459.     {
  460.     TWindow    * wobj;
  461.     
  462.     if (anEvent->what != updateEvt)
  463.         wobj = GetWindowObject(MyFrontNonFloatingWindow());
  464.     else
  465.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  466.  
  467.     if (wobj != nil)
  468. #if    qInlineInputAware
  469.         // give text services a chance to set the cursor shape
  470.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  471.             ;    // do nothing, TSM did it for me
  472.         else    
  473. #endif
  474.             wobj->AdjustCursor(anEvent);
  475.     
  476.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  477.         return;
  478.         
  479.     else switch (anEvent->what)
  480.         {
  481.         case    nullEvent:
  482.             if (wobj != nil)
  483.                 wobj->Idle(anEvent);
  484.             break;
  485.             
  486.         case    mouseDown:
  487.             HandleMouseDown(wobj,anEvent);
  488.             break;
  489.         
  490.         case    keyDown:
  491.         case    autoKey:
  492.             if (anEvent->modifiers & cmdKey)
  493.                 {
  494.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  495. #if    qInlineInputAware
  496.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  497. #endif
  498.                     HandleMenu(wobj,menuResult);
  499.                 HiliteMenu(0);
  500.                 }
  501.             else if (wobj != nil)
  502.                 wobj->KeyDown(anEvent);
  503.             break;
  504.             
  505.         case    updateEvt:
  506.             {
  507.             GrafPtr        oldPort;
  508.             WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  509.                 
  510.             GetPort(&oldPort);
  511.             SetPort(aWindow);
  512.             BeginUpdate(aWindow);
  513.             if (wobj != nil)
  514.                 wobj->Draw();
  515.             EndUpdate(aWindow);
  516.             SetPort(oldPort);
  517.             }
  518.             break;
  519.             
  520.         case diskEvt:
  521.             if (anEvent->message >> 16)
  522.                 {
  523.                 static    Point    where = {50,50};
  524.                 (void) DIBadMount(where,anEvent->message);
  525.                 }
  526.             break;
  527.                 
  528.         case    osEvt:
  529.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  530.                 {
  531.                 case    mouseMovedMessage:
  532.                     break;
  533.                     
  534.                 case    suspendResumeMessage:                    
  535.  
  536.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  537.  
  538.                     if (anEvent->message & resumeFlag)
  539.                         {
  540.                         if (anEvent->message & convertClipboardFlag)
  541.                             ReadLocalClipboardFromScrap();
  542.  
  543.                         gRunQuantum = gForegroundRunQuantum;
  544.                         gSleepQuantum = gForegroundSleepQuantum;
  545.                         }
  546.                     else
  547.                         {
  548.                         if (anEvent->message & convertClipboardFlag)
  549.                             WriteLocalClipboardToScrap();
  550.                         gRunQuantum = gBackgroundRunQuantum;
  551.                         gSleepQuantum = gBackgroundSleepQuantum;
  552.                         }
  553.  
  554.                     break;
  555.                 }
  556.             break;
  557.         
  558.         case    kHighLevelEvent:
  559.             (void) AEProcessAppleEvent(anEvent);
  560.             break;
  561.             
  562.         default:
  563.             break;
  564.         }
  565.     }
  566.  
  567. void
  568. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  569.     {
  570.     WindowPtr    aWindow;
  571.     TWindow        *wobj;
  572.     short        partCode;
  573.  
  574.     partCode = FindWindow(anEvent->where,&aWindow);
  575.     wobj = GetWindowObject(aWindow);
  576.     switch(partCode)
  577.         {
  578.         case    inMenuBar:
  579.             long    menuResult = MenuSelect(anEvent->where);
  580. #if    qInlineInputAware
  581.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  582. #endif
  583.                 HandleMenu(topWindowObj,menuResult);
  584.             HiliteMenu(0);
  585.             break;
  586.             
  587.         case    inSysWindow:
  588.             SystemClick(anEvent,aWindow);
  589.             break;
  590.             
  591.         case    inContent:
  592.             if (wobj)
  593.                 {
  594.                 GrafPtr    oldPort;
  595.                 
  596.                 GetPort(&oldPort);
  597.                 SetPort(aWindow);
  598.                 GlobalToLocal(&anEvent->where);
  599.                 wobj->Click(anEvent);
  600.                 SetPort(aWindow);
  601.                 }
  602.             break;
  603.             
  604.         case    inDrag:
  605.             if (wobj)
  606.                 wobj->Drag(anEvent->where);
  607.             break;
  608.             
  609.         case    inGrow:
  610.             if (wobj)
  611.                 wobj->Grow(anEvent->where);
  612.             break;
  613.             
  614.         case    inGoAway:
  615.             if (TrackGoAway(aWindow,anEvent->where))
  616.                 HandleClose(aWindow);
  617.             break;
  618.  
  619.         case    inZoomIn:
  620.         case    inZoomOut:
  621.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  622.                 wobj->Zoom(partCode);
  623.             break;
  624.             
  625.         default:
  626.             break;
  627.         }
  628.     }
  629.     
  630.  
  631. void
  632. HandleClose(WindowPtr aWindow)
  633.     {
  634.     short    windowKind;
  635.     TWindow    *wobj;
  636.     
  637.     if (aWindow)
  638.         {
  639.         windowKind = ((WindowPeek) aWindow)->windowKind;
  640.         if (windowKind < 0)
  641.             {
  642.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  643.             }
  644.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  645.                     wobj->CanClose() &&
  646.                     wobj->Close() &&
  647.                     wobj->DeleteAfterClose())
  648.             {
  649.             delete wobj;
  650.             }
  651.         }
  652.     }
  653.